import * as mockData from './mockData'
import type { Data } from '@/types/global'

/**
 * 根据提供的选项和对象名称加载JSON格式的模拟响应数据。
 *
 * @param options 包含请求方法和URL等信息的选项对象。
 * @param objName mockData对象中要加载的模拟数据的键名。
 * @returns 返回Data<any>类型的模拟响应数据。
 */
function loadJSON(options: any, objName: string): Data<any> {
  console.log(`REQUEST: ${options.method} ${options.url}: `, options)
  console.log('RESPONSE: ', (mockData as any)[objName])
  return (mockData as any)[objName]
}

/**
 * 创建一个表示请求成功的模拟响应。
 *
 * @param options 包含请求信息的选项对象（此函数未实际使用这些信息）。
 * @returns 返回Data<any>类型的成功响应。
 */
const success = (options: any): Data<any> => {
  const response: Data<any> = {
    code: '0',
    msg: '请求成功',
    result: null,
  }
  console.log(`REQUEST: ${options.method} ${options.url}: `, options)
  console.log('RESPONSE: ', response)
  return response
}

/**
 * 创建一个表示请求失败的模拟响应。
 *
 * @param options 包含请求信息的选项对象（此函数未实际使用这些信息）。
 * @returns 返回Data<any>类型的失败响应。
 */
const failure = (options: any): Data<any> => {
  const response: Data<any> = {
    code: '1',
    msg: '请求失败',
    result: null,
  }
  console.log(`REQUEST: ${options.method} ${options.url}: `, options)
  console.log('RESPONSE: ', response)
  return response
}

// 用于存储模拟请求配置的映射表
const configurations: Map<string | RegExp, Map<string, any>> = new Map()

/**
 * 检查给定的URL是否与配置的URL匹配。
 *
 * @param url 要检查的URL。
 * @param rurl 配置的URL，可以是字符串或正则表达式。
 * @returns 如果匹配则返回true，否则返回false。
 */
function isUrlMatching(url: string, rurl: string | RegExp): boolean {
  if (typeof rurl === 'string') {
    return url === rurl
  } else if (rurl instanceof RegExp) {
    return rurl.test(url)
  } else {
    throw new TypeError('The second argument must be a string or a RegExp.')
  }
}

/**
 * 添加模拟请求配置。
 *
 * @param rurl 请求的URL模式，可以是字符串或正则表达式。
 * @param rtype 请求的方法类型（如GET、POST）。
 * @param template 用于生成模拟响应的模板函数。
 */
function mock(rurl: string | RegExp, rtype: string, template: any) {
  if (!configurations.has(rurl)) {
    configurations.set(rurl, new Map())
  }
  const innerMap = configurations.get(rurl)!
  innerMap.set(rtype, template)
}

function mockRequest(option: UniApp.RequestOptions): any | null {
  for (const [rurl, innerMap] of configurations.entries()) {
    if (isUrlMatching(option.url, rurl)) {
      for (const [rtype, template] of innerMap.entries()) {
        if (option.method === rtype) {
          return template(option)
        }
      }
    }
  }
  return null
}

// 配置模拟请求
mock('/login', 'POST', (options: any) => loadJSON(options, 'authorization'))
mock('/login/wxMin', 'POST', (options: any) => loadJSON(options, 'authorization'))
mock('/login/wxMin/simple', 'POST', (options: any) => loadJSON(options, 'authorization'))

export default mockRequest
